<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 3.9.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"mjava.top","root":"/","scheme":"Muse","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":true},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="浅水是喧哗的，深水是沉默的">
<meta name="keywords" content="Java,Linux,Spring,Jenkins,Docker,RocketMQ,Vue">
<meta property="og:type" content="website">
<meta property="og:title" content="灰色World">
<meta property="og:url" content="http://mjava.top/page/2/index.html">
<meta property="og:site_name" content="灰色World">
<meta property="og:description" content="浅水是喧哗的，深水是沉默的">
<meta property="og:locale" content="zh-CN">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="灰色World">
<meta name="twitter:description" content="浅水是喧哗的，深水是沉默的">

<link rel="canonical" href="http://mjava.top/page/2/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>灰色World</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="灰色World" type="application/atom+xml"><!-- hexo-inject:begin --><!-- hexo-inject:end -->
<link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>

<body itemscope itemtype="http://schema.org/WebPage">
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">灰色World</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/greycode9" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener external nofollow noreferrer" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/java-class-init/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/java-class-init/" class="post-title-link" itemprop="url">Java类初始化</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:01:03" itemprop="dateCreated datePublished" datetime="2020-09-16T15:01:03+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="代码结果？"><a href="#代码结果？" class="headerlink" title="代码结果？"></a>代码结果？</h2><p>首先，我们来看看下面的代码的输出的结果，可以先试着想一下</p>
<p><img src="http://cdn.mjava.top/blog/20200725004926.png" alt></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//结果</span></span><br><span class="line">Code</span><br><span class="line">公众号</span><br></pre></td></tr></table></figure>

<p>这时候有同学就会想，以前不是说类加载时，静态代码块都会加载的嘛！怎么<code>Test1</code>里的静态代码块没有加载呢？下面就来看看到底怎么回事</p>
<h2 id="类的生命周期"><a href="#类的生命周期" class="headerlink" title="类的生命周期"></a>类的生命周期</h2><p>了解类加载前，首先熟悉一下类的生命周期</p>
<p><img src="http://cdn.mjava.top/blog/20200725003859.png" alt></p>
<p>这里注意几个点：</p>
<ul>
<li><code>解析阶段</code>可以在<code>初始化阶段</code>之后，这是为了支持Java语言的运行时绑定特性（也称为<code>动态绑定</code>或<code>晚期绑定</code>）</li>
<li>这些阶段通常都是互相交叉地混合进行的，会在一个阶段执行的过程中调用、激活另一个阶段。</li>
</ul>
<h2 id="初始化和实例化"><a href="#初始化和实例化" class="headerlink" title="初始化和实例化"></a>初始化和实例化</h2><p>我相信很多人跟我刚开始一样，搞不清他们两个的区别，搞不清<code>new</code>一个对象，到底是对这个对象进行了初始化还是实例化呢？</p>
<ul>
<li><p><code>初始化</code>：是完成程序执行前的准备工作。在这个阶段，静态的（变量，方法，代码块）会被执行。同时在会开辟一块存储空间用来存放静态的数据。初始化只在类加载的时候执行<code>一次</code>。</p>
</li>
<li><p><code>实例化</code>：是指创建一个对象的过程。这个过程中会在堆中开辟内存，将一些非静态的方法，变量存放在里面。在程序执行的过程中，可以创建多个对象，既多次实例化。每次实例化都会开辟一块新的内存。</p>
<p><img src="http://cdn.mjava.top/blog/20200725183421.png" alt></p>
</li>
</ul>
<h2 id="类的初始化"><a href="#类的初始化" class="headerlink" title="类的初始化"></a>类的初始化</h2><p>《Java虚拟机规范》中并没有对<code>加载</code>进行强制约束，这点可以交给虚拟机的具体实现来自由把握。但是对于<code>初始化阶段</code>，《Java虚拟机规范》则是严格规定了有且只有<code>六种情况</code>必须立即对类进行“初始化”（而加载、验证、准备自然需要在此之前开始）：</p>
<ul>
<li><p>遇到<code>new</code>、<code>getstatic</code>、<code>putstatic</code>或<code>invokestatic</code>这四条字节码指令时，如果类型没有进行过初始化，则需要先触发其初始化阶段。那到底什么时候能够生成这些指令呢？其实看下字节码就都明白了</p>
<p><img src="http://cdn.mjava.top/blog/20200725172134.png" alt></p>
</li>
<li><p>使用<code>java.lang.reflect</code>包的方法对类型进行<code>反射调用</code>的时候，如果类型没有进行过初始化，则需要先触发其初始化。</p>
</li>
<li><p>当初始化类的时候，如果发现其<code>父类</code>还没有进行过初始化，则需要先触发其父类的初始化。</p>
</li>
<li><p>当虚拟机启动时，用户需要指定一个要执行的<code>主类</code>（包含main()方法的那个类），虚拟机会先初始化这个主类。</p>
</li>
<li><p>当使用JDK 7新加入的动态语言支持时，如果一个<code>java.lang.invoke.MethodHandle</code>实例最后的解析结果为<code>REF_getStatic</code>、<code>REF_putStatic</code>、<code>REF_invokeStatic</code>、<code>REF_newInvokeSpecial</code>四种类型的方法句柄，并且这个方法句柄对应的类没有进行过初始化，则需要先触发其初始化。</p>
</li>
<li><p>当一个接口中定义了<code>JDK 8</code>新加入的默认方法（被<code>default关键字</code>修饰的接口方法）时，如果有这个接口的实现类发生了初始化，那该接口要在其之前被初始化。</p>
</li>
</ul>
<blockquote>
<p><code>java.lang.invoke.MethodHandle</code> 是<code>JDK7</code>中新加入类似反射功能的一个类</p>
</blockquote>
<h2 id="被动引用"><a href="#被动引用" class="headerlink" title="被动引用"></a>被动引用</h2><p>对于以上这六种会触发类型进行<code>初始化</code>的场景，《Java虚拟机规范》中使用了一个非常强烈的限定语——“有且只有”，这六种场景中的行为称为对一个类型进行<code>主动引用</code>。除此之外，所有引用类型的方式都不会触发初始化，称为<code>被动引用。</code></p>
<p>像文章一开始的代码，就属于被动引用，对于静态字段，<strong>只有直接定义这个字段的类才会被初始化</strong>，因此通过其子类来引用父类中定义的静态字段，只会触发父类的初始化而不会触发子类的初始化。</p>
<h3 id="例子1–对象数组"><a href="#例子1–对象数组" class="headerlink" title="例子1–对象数组"></a>例子1–对象数组</h3><p>直接上图</p>
<p><img src="http://cdn.mjava.top/blog/20200725184328.png" alt></p>
<p>以上代码执行后并不会输出<code>灰色</code>两个字，因为创建对象数组时并没有去初始化<code>Test1</code>这个类，而是用<code>anewarray</code>字节码指令去初始化了另外一个类，它是一个由虚拟机自动生成的、直接继承于java.lang.Object的子类。</p>
<blockquote>
<p>拓展：数组越界检查没有封装在数组元素的访问类中，而是封装在数组访问的<code>xaload</code>,<code>xastore</code>字节码指令中</p>
</blockquote>
<h3 id="例子2–final修饰的静态字段"><a href="#例子2–final修饰的静态字段" class="headerlink" title="例子2–final修饰的静态字段"></a>例子2–final修饰的静态字段</h3><ul>
<li>被<code>final</code>修饰的静态字段</li>
</ul>
<p><img src="http://cdn.mjava.top/blog/20200725194122.png" alt></p>
<p>此时运行该代码时，只会输出<code>灰色Code</code>字样，<code>Test1</code>并没有触发初始化阶段。这是因为在<code>编译阶段</code>通过<code>常量传播优化</code>，已经将此常量的值<code>灰色Code</code>直接存储在<code>ClassLoadTest</code>类的常量池中，所以当<code>ClassLoadTest</code>类调用<code>Test1</code>里的<code>value</code>时，都变成了对自身常量池的调用，和<code>Test1</code>类没有任何关系。</p>
<ul>
<li><p>没有<code>final</code>修饰的静态字段</p>
<p><img src="http://cdn.mjava.top/blog/20200725194514.png" alt></p>
</li>
</ul>
<p>没有使用<code>final</code>修饰的静态变量，字节码出现了<code>getstatic</code>，所以触发<code>Test1</code>的初始化阶段，此时运行结果将会输出<code>灰色</code>和<code>灰色Code</code></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/thread/create-thread-3/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/thread/create-thread-3/" class="post-title-link" itemprop="url">创建线程的3种方式</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-06-22 16:29:38" itemprop="dateCreated datePublished" datetime="2020-06-22T16:29:38+00:00">2020-06-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JAVA/" itemprop="url" rel="index"><span itemprop="name">JAVA</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Java线程状态变迁图"><a href="#Java线程状态变迁图" class="headerlink" title="Java线程状态变迁图"></a>Java线程状态变迁图</h2><p><img src="http://cdn.mjava.top/blog/20200602150941.jpeg" alt="Java线程状态变迁图"></p>
<h2 id="构造一个线程"><a href="#构造一个线程" class="headerlink" title="构造一个线程"></a>构造一个线程</h2><p>在线程执行<code>start()</code>方法之前,首先需要初始化(NEW)一个线程,初始化的时候,可以设置线程名称,线程所属的线程组、线程优先级、是否是Daemon线程等信息。</p>
<p><strong>Thread常见参数及设置方法:</strong></p>
<ul>
<li><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//线程是否是守护线程  默认false</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span>     daemon = <span class="keyword">false</span>;</span><br><span class="line"><span class="comment">//设置方法</span></span><br><span class="line">Thread thread=<span class="keyword">new</span> Thread();</span><br><span class="line">thread.setDaemon(<span class="keyword">true</span>);</span><br></pre></td></tr></table></figure>
</li>
<li><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//线程名字	默认"Thread-" + nextThreadNum()</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> String name;</span><br><span class="line"><span class="comment">//设置方法</span></span><br><span class="line">Thread thread=<span class="keyword">new</span> Thread();</span><br><span class="line">thread.setName(<span class="string">"myThread"</span>); <span class="comment">//不能设置为null,会报异常</span></span><br></pre></td></tr></table></figure>
</li>
<li><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//线程优先级  是否起作用和操作系统及虚拟机版本相关</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> priority;																</span><br><span class="line"><span class="comment">//设置方法  范围:1-10  默认5</span></span><br><span class="line">myThread.setPriority(<span class="number">1</span>);</span><br></pre></td></tr></table></figure>



</li>
</ul>
<h3 id="Thread源码构造方法"><a href="#Thread源码构造方法" class="headerlink" title="Thread源码构造方法"></a>Thread源码构造方法</h3><p>在Thread源码中,一共提供了<code>9种</code>构造方法.</p>
<p><img src="http://cdn.mjava.top/blog/20200602151437.png" alt></p>
<p>从这些构造方法中,大致可以分为<code>有Runnable构造参数</code>的,和<code>无Runnable构造参数</code>两大类,无Runnable构造参数的就需要去继承<code>Thread</code>来重写<code>run()</code>方法<font color="grey">(注:<code>Thread</code>也实现了Runnable接口)</font>,有Runnable构造参数的,就实现Runnable接口的run方法,然后通过构造参数,把实现Runnable接口的实例传入Thread.</p>
<h3 id="无返回值的线程"><a href="#无返回值的线程" class="headerlink" title="无返回值的线程"></a>无返回值的线程</h3><p>可以看到,通过集成<code>Thread</code>类和实现<code>Runnable</code>接口的<code>run()</code>方法返回值都是<code>void</code>.这类是没有返回值的</p>
<h4 id="方法一-继承Thread类创建一个线程"><a href="#方法一-继承Thread类创建一个线程" class="headerlink" title="方法一:继承Thread类创建一个线程"></a>方法一:继承Thread类创建一个线程</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//继承Thread类,重写run方法</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">extends</span> <span class="title">Thread</span></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"继承Thread,重写run方法"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ThreadTest</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        MyThread myThread=<span class="keyword">new</span> MyThread();</span><br><span class="line">        myThread.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="方法二-实现Runnable接口创建线程"><a href="#方法二-实现Runnable接口创建线程" class="headerlink" title="方法二:实现Runnable接口创建线程"></a>方法二:实现Runnable接口创建线程</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//实现Runnable接口的run方法,然后以构造参数的形式设置Thread的target</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyRun</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"实现Runnable方法"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ThreadTest</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        MyRun myRun=<span class="keyword">new</span> MyRun();</span><br><span class="line">        Thread thread=<span class="keyword">new</span> Thread(myRun);</span><br><span class="line">        thread.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="有返回值的线程"><a href="#有返回值的线程" class="headerlink" title="有返回值的线程"></a>有返回值的线程</h3><p>上面两个方法,都有一个共同缺点,就是<strong>没有返回值</strong>,当有一些特殊需求时,比如开启一个线程,用来计算一些东西,或者是处理另外一些需要返回数据的业务,这时就需要借助<code>FutureTask</code>来完成了</p>
<h4 id="方法三-通过FutureTask创建一个线程"><a href="#方法三-通过FutureTask创建一个线程" class="headerlink" title="方法三:通过FutureTask创建一个线程"></a>方法三:通过FutureTask创建一个线程</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//实现Callable接口的call方法   类似实现Runnable的run方法</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyCall</span> <span class="keyword">implements</span> <span class="title">Callable</span>&lt;<span class="title">Integer</span>&gt;</span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Integer <span class="title">call</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="comment">//计算1+1</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>+<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ThreadTest</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        MyCall myCall=<span class="keyword">new</span> MyCall();</span><br><span class="line">        <span class="comment">//创建异步任务</span></span><br><span class="line">        FutureTask&lt;Integer&gt; futureTask=<span class="keyword">new</span> FutureTask&lt;&gt;(myCall);</span><br><span class="line">        Thread thread2=<span class="keyword">new</span> Thread(futureTask);</span><br><span class="line">        thread2.start();</span><br><span class="line">        <span class="comment">//获取线程执行结果</span></span><br><span class="line">        Integer res=futureTask.get();</span><br><span class="line">        System.out.println(res); <span class="comment">//输出2</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>使用继承方式的好处是方便传参，你可以在子类里面添加成员变量，通过set方法设置参数或者通过构造函数进行传递，而如果使用Runnable方式，则只能使用主线程里面被声明为final的变量。不好的地方是Java不支持多继承，如果继承了Thread类，那么子类不能再继承其他类，而Runable则没有这个限制。前两种方式都没办法拿到任务的返回结果，但是Futuretask方式可以。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/tool/git-tool-command/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/tool/git-tool-command/" class="post-title-link" itemprop="url">吐血整理Git常用命令</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-06-22 16:27:25" itemprop="dateCreated datePublished" datetime="2020-06-22T16:27:25+00:00">2020-06-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Tool/" itemprop="url" rel="index"><span itemprop="name">Tool</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Git常用命令"><a href="#Git常用命令" class="headerlink" title="Git常用命令"></a>Git常用命令</h2><h2 id="Git简介"><a href="#Git简介" class="headerlink" title="Git简介"></a>Git简介</h2><p>Git 是用于 Linux<a href="https://baike.baidu.com/item/内核" rel="noopener external nofollow noreferrer" target="_blank">内核</a>开发的<a href="https://baike.baidu.com/item/版本控制" rel="noopener external nofollow noreferrer" target="_blank">版本控制</a>工具。与常用的版本控制工具 CVS, Subversion 等不同，它采用了分布式版本库的方式，不必服务器端软件支持（wingeddevil注：这得分是用什么样的服务端，使用http协议或者git协议等不太一样。并且在push和pull的时候和服务器端还是有交互的。），使<a href="https://baike.baidu.com/item/源代码" rel="noopener external nofollow noreferrer" target="_blank">源代码</a>的发布和交流极其方便。 Git 的速度很快，这对于诸如 Linux kernel 这样的大项目来说自然很重要。 Git 最为出色的是它的合并跟踪（merge tracing）能力。</p>
<p>git对于很多人来说,真的是又爱又恨,用的好可以提示开发效率;用不好,解决各种冲突就要累的你半死</p>
<h2 id="git结构"><a href="#git结构" class="headerlink" title="git结构"></a>git结构</h2><blockquote>
<p>网上有 我就不画了</p>
</blockquote>
<p><img src="http://cdn.mjava.top/blog/20200605001853.png" alt="git结构图"></p>
<ul>
<li><p>workspace    相当于就是我们的本地电脑上的文件</p>
</li>
<li><p>Index    缓存区</p>
</li>
<li><p>Repository    本地仓库</p>
</li>
<li><p>Remote    远程仓库(github/gitlab/gitee)</p>
</li>
</ul>
<h2 id="git命令"><a href="#git命令" class="headerlink" title="git命令"></a>git命令</h2><p>git官方提供的命令多达几百个,可是我们日常却用不到这么多</p>
<p>所以我就整理了一下日常使用的命令</p>
<p>现在关注微信公招:<code>灰色Code</code></p>
<p>回复关键字:<code>git</code></p>
<p>就可以获取思维导图高清图片及导图源地址</p>
<p><img src="http://cdn.mjava.top/blog/20200605002904.jpg" alt></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/spring/apring-aop-ann/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/spring/apring-aop-ann/" class="post-title-link" itemprop="url">创建一个自定义注解</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-06-22 16:23:56" itemprop="dateCreated datePublished" datetime="2020-06-22T16:23:56+00:00">2020-06-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Spring/" itemprop="url" rel="index"><span itemprop="name">Spring</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>平时在用springBoot的使用，常常会用到<code>@Service</code>，<code>@Compent</code>等等注解，简化了我们的开发流程，提升了开发效率.那如何自己来写一个注解呢？下面就来介绍一下。</p>
<h2 id="写一个注解"><a href="#写一个注解" class="headerlink" title="写一个注解"></a>写一个注解</h2><p>创建一个注解主要分两部分，一部分是创建<strong>注解类</strong>，一部分是创建一个<strong>切面类</strong>。</p>
<h3 id="创建注解类"><a href="#创建注解类" class="headerlink" title="创建注解类"></a>创建注解类</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Target</span>(&#123;ElementType.METHOD&#125;)</span><br><span class="line"><span class="meta">@Retention</span>(RetentionPolicy.RUNTIME)</span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> MyAnn &#123;</span><br><span class="line">    <span class="function">String <span class="title">value</span><span class="params">()</span> <span class="keyword">default</span> "d"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>创建注解类的关键字就是<code>@interface</code>，这个注解类设置了一个<code>value</code>变量，默认值为d；</p>
<p>在注解类上面还有<code>@Target</code>和<code>@Retention</code>注解，下面来说说创建注解类时需要用到的几个注解：</p>
<h4 id="Target"><a href="#Target" class="headerlink" title="@Target"></a><code>@Target</code></h4><p>用来标记这个注解可以用于哪些地方，与<code>ElementType</code>枚举类搭配使用，那这个枚举类里面有什么内容呢？</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">enum</span> ElementType &#123;</span><br><span class="line">    <span class="comment">/** 类，接口（包括注释类型）或枚举声明*/</span></span><br><span class="line">    TYPE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 字段声明（包括枚举常量）*/</span></span><br><span class="line">    FIELD,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 方法声明*/</span></span><br><span class="line">    METHOD,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 形式参数（形参-调用方法时传入的参数）声明 */</span></span><br><span class="line">    PARAMETER,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 构造函数声明 */</span></span><br><span class="line">    CONSTRUCTOR,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 局部变量声明 */</span></span><br><span class="line">    LOCAL_VARIABLE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 注释类型声明 */</span></span><br><span class="line">    ANNOTATION_TYPE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 包声明 */</span></span><br><span class="line">    PACKAGE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 类型参数声明</span></span><br><span class="line"><span class="comment">     * java8新特性：</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@since</span> 1.8</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    TYPE_PARAMETER,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 任何类型声明 </span></span><br><span class="line"><span class="comment">     * java8新特性：</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@since</span> 1.8</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    TYPE_USE</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="Retention"><a href="#Retention" class="headerlink" title="@Retention"></a><code>@Retention</code></h4><p>该注解表示自定义注解的生命周期</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">enum</span> RetentionPolicy &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 注释将被编译器丢弃。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    SOURCE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 注释由编译器记录在类文件中</span></span><br><span class="line"><span class="comment">     * 但不必在运行时由VM保留。 这是默认值</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    CLASS,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">   	 *注释由编译器记录在类文件中，并且</span></span><br><span class="line"><span class="comment">     *在运行时由VM保留，因此可以以反射方式读取它们。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    RUNTIME</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="写一个切面类"><a href="#写一个切面类" class="headerlink" title="写一个切面类"></a>写一个切面类</h2><p>因为用到了切面，所以我们要先导入<code>Spring AOP</code>这个依赖包。</p>
<figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!--SpringBoot项目导入AOP--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-aop<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="创建切面类"><a href="#创建切面类" class="headerlink" title="创建切面类"></a>创建切面类</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyAnnAop</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Logger logger= LoggerFactory.getLogger(MyAnnAop.class);</span><br><span class="line">    <span class="meta">@Pointcut</span>(<span class="string">"@annotation(com.example.demo.annotation.MyAnn)"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">ann</span><span class="params">()</span></span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Before</span>(<span class="string">"ann()"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(JoinPoint joinPoint)</span></span>&#123;</span><br><span class="line">        logger.info(<span class="string">"打印：开始前"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterReturning</span>(value = <span class="string">"ann()"</span>,returning = <span class="string">"res"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">dochange</span><span class="params">(JoinPoint joinPoint,Object res)</span></span>&#123;</span><br><span class="line">        logger.info(<span class="string">"AfterReturning通知开始-获取数据:&#123;&#125;"</span>,res);</span><br><span class="line">        <span class="comment">//获取数据</span></span><br><span class="line">        Map&lt;String,String&gt; map= (Map&lt;String, String&gt;) res;</span><br><span class="line">        <span class="comment">//添加新值</span></span><br><span class="line">        map.put(<span class="string">"s1"</span>,<span class="string">"我是在AOP中添加的新值"</span>);</span><br><span class="line">        <span class="keyword">return</span> map;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Spring-AOP说明"><a href="#Spring-AOP说明" class="headerlink" title="Spring AOP说明"></a>Spring AOP说明</h3><blockquote>
<p>具体可以查阅Spring AOP相关资料</p>
</blockquote>
<table>
<thead>
<tr>
<th>注解</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>@Before</code></td>
<td>前置通知，在连接点方法前调用</td>
</tr>
<tr>
<td><code>@Around</code></td>
<td>环绕通知，它将覆盖原有方法，但是允许你通过反射调用原有方法</td>
</tr>
<tr>
<td><code>@After</code></td>
<td>后置通知，在连接点方法后调用</td>
</tr>
<tr>
<td><code>@AfterReturning</code></td>
<td>返回通知，在连接点方法执行并正常返回后调用，要求连接点方法在执行过程中没有发生异常</td>
</tr>
<tr>
<td><code>@AfterThrowing</code></td>
<td>异常通知，当连接点方法异常时调用</td>
</tr>
</tbody></table>
<h2 id="使用自定义的注解"><a href="#使用自定义的注解" class="headerlink" title="使用自定义的注解"></a>使用自定义的注解</h2><p>这里使用普通的<code>SpringBoot</code>来使用注解，创建一个<strong>Service</strong>,在里面使用注解，然后才控制层调用</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//服务层</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestService</span> </span>&#123;</span><br><span class="line">    <span class="meta">@MyAnn</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Map <span class="title">test</span><span class="params">()</span></span>&#123;</span><br><span class="line">        Map&lt;String,String&gt;  map=<span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        map.put(<span class="string">"t1"</span>,<span class="string">"我是在Service设置的值"</span>);</span><br><span class="line">        <span class="keyword">return</span> map;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//控制层</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test2</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Logger logger= LoggerFactory.getLogger(Test2.class);</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TestService testService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping</span>(<span class="string">"/test"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">test</span><span class="params">(String id)</span></span>&#123;</span><br><span class="line">        Map&lt;String,String&gt; s=testService.test();</span><br><span class="line">        logger.info(<span class="string">"控制层输出：&#123;&#125;"</span>,s.get(<span class="string">"s1"</span>));</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"sccess"</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="输出"><a href="#输出" class="headerlink" title="输出"></a>输出</h4><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">com.example.demo.aop.MyAnnAop : AfterReturning通知开始-获取数据:&#123;t1=我是在Service设置的值&#125;</span><br><span class="line">com.example.demo.web.Test2    : 控制层输出：我是在AOP中添加的新值</span><br></pre></td></tr></table></figure>

<h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><p>上面那样使用注解是没问题的，但是如果是下面这样使用，<code>AOP</code>就会<strong>失效</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test2</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Logger logger= LoggerFactory.getLogger(Test2.class);</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TestService testService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping</span>(<span class="string">"/test"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">test</span><span class="params">(String id)</span></span>&#123;</span><br><span class="line">        Map&lt;String,String&gt; s=<span class="keyword">this</span>.test2();</span><br><span class="line">        logger.info(<span class="string">"控制层输出：&#123;&#125;"</span>,s.get(<span class="string">"s1"</span>));</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"sccess"</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@MyAnn</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Map <span class="title">test2</span><span class="params">()</span></span>&#123;</span><br><span class="line">        Map&lt;String,String&gt;  map=<span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        map.put(<span class="string">"t1"</span>,<span class="string">"我是在控制层设置的值"</span>);</span><br><span class="line">        <span class="keyword">return</span> map;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="输出-1"><a href="#输出-1" class="headerlink" title="输出"></a>输出</h4><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">com.example.demo.web.Test2       : 控制层输出：null</span><br></pre></td></tr></table></figure>

<p>这是应为内部方法调用，调用的是具体方法，并没有调用使用AOP后生成的代理方法</p>
<p>具体参考资料：</p>
<ul>
<li><a href="https://blog.csdn.net/Daybreak1209/article/details/82982674" rel="noopener external nofollow noreferrer" target="_blank">https://blog.csdn.net/Daybreak1209/article/details/82982674</a></li>
<li><a href="https://blog.csdn.net/u013151053/article/details/106124048?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase" rel="noopener external nofollow noreferrer" target="_blank">https://blog.csdn.net/u013151053/article/details/106124048?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase</a></li>
<li><a href="https://zhewuzhou.github.io/2018/09/01/Spring_AOP_Trap/" rel="noopener external nofollow noreferrer" target="_blank">https://zhewuzhou.github.io/2018/09/01/Spring_AOP_Trap/</a></li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/jvm-gc-alg/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/jvm-gc-alg/" class="post-title-link" itemprop="url">JVM4种垃圾收集算法</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-05-29 10:31:30" itemprop="dateCreated datePublished" datetime="2020-05-29T10:31:30+00:00">2020-05-29</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>垃圾收集算法可以划分为“引用计数式垃圾收集”（Reference Counting GC）和“追踪式垃圾收集”（Tracing GC）两大类，这两类也常被称作“直接垃圾收集”和“间接垃圾收集”。</p>
<h2 id="标记-清除算法"><a href="#标记-清除算法" class="headerlink" title="标记-清除算法"></a>标记-清除算法</h2><ul>
<li><strong>标记过程</strong>就是对象是否属于垃圾的判定过程(<strong>采用可达分析算法GC Roots</strong>)</li>
<li>算法分为<strong>“标记”</strong>和<strong>“清除”</strong>两个阶段：首先标记出所有需要回收的对象，在标记完成后，统一回收掉所有被标记的对象，<strong>也可以反过来</strong>，标记存活的对象，统一回收所有未被标记的对象。</li>
</ul>
<h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h3><ul>
<li>执行效率不稳定，如果Java堆中包含大量对象，而且<strong>其中大部分是需要被回收的</strong>，这时必须进行大量标记和清除的动作，导致标记和清除两个过程的<strong>执行效率都随对象数量增长而降低</strong>；</li>
<li>第二个是内存空间的碎片化问题，标记、清除之后会<strong>产生大量不连续的内存碎片</strong>，空间碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时<strong>无法找到足够的连续内存</strong>而不得不<strong>提前触发另一次垃圾收集动作</strong>。</li>
<li><img src="http://cdn.mjava.top/blog/20200529100358.png" alt></li>
</ul>
<p><img src="http://cdn.mjava.top/blog/20200528203926.jpeg" alt="标记清除算法"></p>
<h2 id="标记-复制算法"><a href="#标记-复制算法" class="headerlink" title="标记-复制算法"></a>标记-复制算法</h2><ul>
<li><p><strong>标记过程</strong>就是对象是否属于垃圾的判定过程(<strong>采用可达分析算法GC Roots</strong>)</p>
</li>
<li><p>它将可用内存按容量划分为<strong>大小相等的两块</strong>，每次只使用其中的一块。</p>
</li>
<li><p>当这一块的内存用完了，就将还<strong>存活着的对象复制到另外一块上面</strong>，然后再把<strong>已使用过的内存空间一次清理掉</strong>。</p>
</li>
</ul>
<h3 id="缺点-1"><a href="#缺点-1" class="headerlink" title="缺点"></a>缺点</h3><ul>
<li>如果内存中<strong>多数对象都是存活的</strong>，这种算法将会<strong>产生大量的内存间复制的开销</strong></li>
<li>代价是将可用内存缩小为了<strong>原来的一半</strong>,空间浪费未免太多了一点.</li>
<li><img src="http://cdn.mjava.top/blog/20200529100420.jpg" alt></li>
</ul>
<p><img src="http://cdn.mjava.top/blog/20200528203952.jpeg" alt="标记复制算法"></p>
<h2 id="标记-整理算法"><a href="#标记-整理算法" class="headerlink" title="标记-整理算法"></a>标记-整理算法</h2><ul>
<li><strong>标记过程</strong>就是对象是否属于垃圾的判定过程(<strong>采用可达分析算法GC Roots</strong>)</li>
<li>在<strong>标记-清除</strong>的算法基础上改进,后续步骤不是直接对可回收对象进行清理，而是让<strong>所有存活的对象都向内存空间一端移动</strong>，然后直接<strong>清理掉边界以外的内存</strong>，</li>
</ul>
<h3 id="缺点-2"><a href="#缺点-2" class="headerlink" title="缺点"></a>缺点</h3><ul>
<li>在有大量存活对象的老年代区域,<strong>移动存活对象</strong>并<strong>更新所有引用</strong>这些对象的地方将会是一种<strong>极为负重</strong>的操作,而且这种对象移动操作<strong>必须全程暂停用户应用程序</strong>才能进行,比<strong>标记-清除</strong>算法停顿时间长.</li>
<li><img src="http://cdn.mjava.top/blog/20200529100506.jpg" alt></li>
</ul>
<p><img src="http://cdn.mjava.top/blog/20200528204014.jpeg" alt="标记整理算法"></p>
<h2 id="分代收集算法"><a href="#分代收集算法" class="headerlink" title="分代收集算法"></a>分代收集算法</h2><p>现代商用虚拟机基于以上算法的优缺点,根据<strong>分代收集理论</strong>,在不同的区域采用了不同的收集算法.</p>
<blockquote>
<p><font color="red">老年代:新生代=2:1</font></p>
</blockquote>
<p><img src="http://cdn.mjava.top/blog/20200529101100.png" alt></p>
<h3 id="新生代"><a href="#新生代" class="headerlink" title="新生代"></a>新生代</h3><blockquote>
<p>堆大小默认比例:<font color="red">Eden:S0:S1=8:1:1</font></p>
<p>采用标记-复制算法</p>
</blockquote>
<p>新生代分为<strong>Eden区</strong>和<strong>Survior区</strong>,而Survior区又分为<strong>From Survior区(S0)</strong>和<strong>To Survior区(S1)</strong>.此区域采用标记-复制算法.每次Minor GC/Young GC时,会把<strong>Eden区</strong>存活的对象复制到<strong>S0区</strong>,然后清空Eden区,当S0区满时,Eden区和S0区存活的对象会复制到<strong>S1区</strong>,然后S0和S0进行交换,永远保持S1为空状态,当新生代的对象经过一定次数的Minor GC还未被回收时,就会把这个对象移到老年代.</p>
<h3 id="老年代"><a href="#老年代" class="headerlink" title="老年代"></a>老年代</h3><blockquote>
<p>采用标记-整理法或标记-清理法</p>
</blockquote>
<p>当老年代Old区域满时,会触发<strong>Full GC</strong>,同时回收新生代和老生代的所有区域.回收后诺内存还是不足时,会引发<strong>OOM异常</strong>;</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/jvm-object-four-quote/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/jvm-object-four-quote/" class="post-title-link" itemprop="url">JAVA四种引用方法使用和对比</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-05-29 10:22:07" itemprop="dateCreated datePublished" datetime="2020-05-29T10:22:07+00:00">2020-05-29</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
                  ，
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/JAVA/" itemprop="url" rel="index"><span itemprop="name">JAVA</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p><img src="http://cdn.mjava.top/blog/20200526225718" alt></p>
<h2 id="强引用（Strongly-Reference）"><a href="#强引用（Strongly-Reference）" class="headerlink" title="强引用（Strongly Reference）"></a>强引用（Strongly Reference）</h2><blockquote>
<p>无论任何情况下，只要强引用关系还存在，垃圾收集器就永远不会回收掉被引用的对象。</p>
<p><font color="red">回收时机:强引用关系不存在时</font></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line">Object obj=<span class="keyword">new</span> Object();</span><br></pre></td></tr></table></figure>

<h2 id="软引用（Soft-Reference）"><a href="#软引用（Soft-Reference）" class="headerlink" title="软引用（Soft Reference）"></a>软引用（Soft Reference）</h2><blockquote>
<p>软引用是用来描述一些还有用，但非必须的对象。只被软引用关联着的对象，在系统将要发生内存溢出异常前，会把这些对象列进回收范围之中进行第二次回收，如果这次回收还没有足够的内存，才会抛出内存溢出异常。</p>
<p><font color="red">回收时机:发送内存溢出异常前</font></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//软引用</span></span><br><span class="line"></span><br><span class="line">SoftReference&lt;Object&gt; srf = <span class="keyword">new</span> SoftReference&lt;Object&gt;(<span class="keyword">new</span> Object());</span><br><span class="line"></span><br><span class="line"><span class="comment">//or</span></span><br><span class="line"></span><br><span class="line">Object obj=<span class="keyword">new</span> Object();</span><br><span class="line">SoftReference&lt;Object&gt; srf = <span class="keyword">new</span> SoftReference&lt;Object&gt;(obj);</span><br><span class="line">obj=<span class="keyword">null</span>;  <span class="comment">//这种方法一定要设置obj为null,否则这个对象除了软引用可达外,还有原来强引用也可达</span></span><br></pre></td></tr></table></figure>

<h3 id="弱引用（Weak-Reference）"><a href="#弱引用（Weak-Reference）" class="headerlink" title="弱引用（Weak Reference）"></a>弱引用（Weak Reference）</h3><blockquote>
<p>弱引用也是用来描述那些非必须对象，但是它的强度比软引用更弱一些，被弱引用关联的对象<strong>只能生存到下一次垃圾收集发生为止</strong>。当垃圾收集器开始工作，无论当前内存是否足够，都会回收掉只被弱引用关联的对象。</p>
<p><font color="red">回收时机:下一次垃圾回收时</font></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//弱引用</span></span><br><span class="line"></span><br><span class="line">WeakReference&lt;Object&gt; wrf = <span class="keyword">new</span> WeakReference&lt;Object&gt;(<span class="keyword">new</span> Object());</span><br><span class="line"></span><br><span class="line"><span class="comment">//or</span></span><br><span class="line">Object obj=<span class="keyword">new</span> Object();</span><br><span class="line">WeakReference&lt;Object&gt; wrf = <span class="keyword">new</span> WeakReference&lt;Object&gt;(<span class="keyword">new</span> Object());</span><br><span class="line">obj=<span class="keyword">null</span>;</span><br></pre></td></tr></table></figure>

<h3 id="虚引用（Phantom-Reference）"><a href="#虚引用（Phantom-Reference）" class="headerlink" title="虚引用（Phantom Reference）"></a>虚引用（Phantom Reference）</h3><blockquote>
<p>虚引用也称为“幽灵引用”或者“幻影引用”，它是最弱的一种引用关系。一个对象是否有虚引用的存在，完全不会对其生存时间构成影响，也无法通过虚引用来取得一个对象实例。</p>
<p><font color="red">回收时机:随时</font></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//虚引用</span></span><br><span class="line">PhantomReference&lt;Object&gt; prf = <span class="keyword">new</span> PhantomReference&lt;Object&gt;(<span class="keyword">new</span> Object(), <span class="keyword">new</span> ReferenceQueue&lt;&gt;());</span><br><span class="line"></span><br><span class="line"><span class="comment">//or</span></span><br><span class="line"></span><br><span class="line">Object obj=<span class="keyword">new</span> Object();</span><br><span class="line">PhantomReference&lt;Object&gt; prf = <span class="keyword">new</span> PhantomReference&lt;Object&gt;(obj, <span class="keyword">new</span> ReferenceQueue&lt;&gt;());</span><br><span class="line">obj=<span class="keyword">null</span>;</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/jvm-object-is-alive/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/jvm-object-is-alive/" class="post-title-link" itemprop="url">JVM判断对象是否还活着的两种方法</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-05-29 10:18:30" itemprop="dateCreated datePublished" datetime="2020-05-29T10:18:30+00:00">2020-05-29</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="引用计数法"><a href="#引用计数法" class="headerlink" title="引用计数法"></a>引用计数法</h2><blockquote>
<p>Java虚拟机<strong>并不是</strong>通过引用计数算法来判断对象是否存活的。</p>
</blockquote>
<p>在对象中添加一个引用计数器，每当有一个地方引用它时，计数器值就加一；当引用失效时，计数器值就减一；任何时刻计数器为零的对象就是不可能再被使用的。</p>
<h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3><ul>
<li>原理简单,判定效率高</li>
</ul>
<h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h3><ul>
<li>不能用于复杂的环境中,比如对象的互相引用问题</li>
</ul>
<h2 id="可达性分析算法"><a href="#可达性分析算法" class="headerlink" title="可达性分析算法"></a>可达性分析算法</h2><blockquote>
<p>Java虚拟机使用此算法来判断对象是否存活</p>
</blockquote>
<p>这个算法的基本思路就是通过一系列称为“<code>GC Roots</code>”的根对象作为起始节点集，从这些节点开始，根据引用关系向下搜索，<strong>搜索过程所走过的路径称为“引用链”（Reference Chain）</strong>，如果某个对象到GCRoots间<strong>没有任何引用链相连</strong>，或者用图论的话来说就是<strong>从GC Roots到这个对象不可达时</strong>，则证明<strong>此对象是不可能再被使用的</strong>。</p>
<p><img src="http://cdn.mjava.top/blog/20200526224246.jpeg" alt></p>
<p>Java中作为GC Roots的对象:</p>
<ul>
<li><p>在虚拟机栈（<strong>栈帧中的本地变量表</strong>）中引用的对象，譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。</p>
</li>
<li><p>在方法区中类静态属性引用的对象，譬如Java类的引用类型静态变量。</p>
</li>
<li><p>在方法区中常量引用的对象，譬如字符串常量池（String Table）里的引用。</p>
</li>
<li><p>在本地方法栈中JNI（即通常所说的Native方法）引用的对象。</p>
</li>
<li><p>Java虚拟机内部的引用，如基本数据类型对应的Class对象，一些常驻的异常对象（比如NullPointExcepiton、OutOfMemoryError）等，还有系统类加载器。</p>
</li>
<li><p>所有被同步锁（synchronized关键字）持有的对象。</p>
</li>
<li><p>反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。</p>
</li>
<li><p><strong>其他对象临时性地加入,共同构成GC Roots</strong></p>
</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/jvm-running-data-area/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/jvm-running-data-area/" class="post-title-link" itemprop="url">JVM运行时数据区域</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-05-26 16:35:47" itemprop="dateCreated datePublished" datetime="2020-05-26T16:35:47+00:00">2020-05-26</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="JVM运行时数据区域"><a href="#JVM运行时数据区域" class="headerlink" title="JVM运行时数据区域"></a>JVM运行时数据区域</h1><p><img src="http://cdn.mjava.top/blog/20200526000623.jpeg" alt="Java虚拟机运行时数据区"></p>
<h3 id="程序计数器"><a href="#程序计数器" class="headerlink" title="程序计数器"></a>程序计数器</h3><ul>
<li><p>线程私有</p>
</li>
<li><p>唯一一个没有规定 OutOfMemoryError 异常 的区域</p>
</li>
<li><p>它可以看作是当前线程所执行的字节码的行号指示器</p>
</li>
<li><p>如果线程正在执行的是一个Java方法，这个计数器记录的是正在执行的虚拟机字节码指令的地址；如果正在执行的是本地（Native）方法，这个计数器值则应为空（Undefined）</p>
</li>
</ul>
<blockquote>
<p>(摘自网上)我们想象下，CPU是怎么知道记住之前A线程，执行到哪一处的？</p>
<p>答案是，CPU根本就不会记住之前执行到哪里了，它只是埋头苦干；那是什么保证了切换线程的程序可以正常执行的；答案是 ： 程序计数器 ；<strong>程序计数器里面保存的是 当前线程执行的字节码的行号</strong>（看着像行号，其实是指令地址）；</p>
<p>那么，我们需要几个程序计数器呢？如果，我们只有一个的话，切换B线程以后，程序计数器里面保存的就是B线程所执行的字节码的行号了，再切换回A线程，就蒙圈了，不知道执行到哪里了，因为，程序计数器里面保存的是B线程当前执行的字节码地址 ；因此，我们可以想象出，要为每个线程都分配一个程序计数器，因此，<strong>程序计数器的内存空间是线程私</strong>有的 ；这样即使线程 A 被挂起，但是线程 A 里面的程序计数器，记住了A线程当前执行到的字节码的指令地址了 ，等再次切回到A线程的时候，看一下程序计数器，就知道之前执行到哪里了！</p>
<p>那么程序计数器，什么时候分配内存呢？我们试想下，一个线程在执行的任何期间，都会失去CPU执行权，因此，我们要从一个线程被创建开始执行，就要无时无刻的记录着该线程当前执行到哪里了！因此，线程计数器，必须是<strong>线程被创建开始执行的时候，就要一同被创建</strong>； </p>
<p>程序计数器，保存的是当前执行的字节码的偏移地址（也就是之前说的行号，其实那不是行号，是指令的偏移地址，只是为了好理解，才说是行号的，），当执行到下一条指令的时候，改变的只是程序计数器中保存的地址，并不需要申请新的内存来保存新的指令地址；因此，永远都不可能内存溢出的；因此，jvm虚拟机规范，也就没有规定，也是<strong>唯一一个没有规定 OutOfMemoryError 异常 的区域</strong>;</p>
<p><strong>当线程执行的是本地方法的时候，程序计数器中保存的值是空（undefined）</strong>；原因很简单：本地方法是C++/C 写的，由系统调用，根本不会产生字节码文件，因此，程序计数器也就不会做任何记录 </p>
</blockquote>
<h3 id="Java虚拟机栈"><a href="#Java虚拟机栈" class="headerlink" title="Java虚拟机栈"></a>Java虚拟机栈</h3><ul>
<li>线程私有</li>
<li>如果线程请求的栈深度大于虚拟机所允许的深度，将抛出<code>StackOverflowError异常</code>；</li>
<li>如果Java虚拟机栈容量可以动态扩展，当栈扩展时无法申请到足够的内存会抛出<code>OutOfMemoryError异常</code>；(<font color="red">HotSpot虚拟机的栈容量是不可以动态扩展的，以前的Classic虚拟机倒是可以。所以在HotSpot虚拟机上是不会由于虚拟机栈无法扩展而导致OutOfMemoryError异常——只要线程申请栈空间成功了就不会有OOM，但是如果申请时就失败，仍然是会出现OOM异常的</font>)</li>
<li><strong>-Xss5m</strong>:    设置5m的栈容量</li>
<li>每个方法执行都会创建一个<strong>栈帧</strong>，栈帧包含局部变量表、操作数栈、动态连接、方法出口等</li>
</ul>
<h3 id="本地方法栈"><a href="#本地方法栈" class="headerlink" title="本地方法栈"></a>本地方法栈</h3><ul>
<li><p>线程私有</p>
</li>
<li><p>与Java虚拟机栈相似</p>
</li>
<li><p>与Java虚拟机栈区别:    Java虚拟机栈为虚拟机执行Java方法（也就是字节码）服务，而本地方法栈则是为虚拟机使用到的本地（Native）方法服务。</p>
</li>
<li><p>Hot-Spot虚拟机直接就把本地方法栈和虚拟机栈合二为一</p>
</li>
<li><p>与虚拟机栈一样，本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError异常</p>
</li>
</ul>
<h3 id="Java堆"><a href="#Java堆" class="headerlink" title="Java堆"></a>Java堆</h3><ul>
<li>线程共享</li>
<li>所有的Java对象实例不一定都在Java堆上分配内存</li>
<li>Java堆既可以被实现成固定大小的，也可以是可扩展的，不过当前主流的Java虚拟机都是按照可扩展来实现的（通过参数<code>-Xmx</code>和<code>-Xms</code>设定）。</li>
<li>如果在Java堆中没有内存完成实例分配，并且堆也无法再扩展时，Java虚拟机将会抛出<strong>OutOfMemoryError异常</strong>。</li>
<li>Java堆是垃圾收集器(Garbage Collected)管理的内存区域</li>
</ul>
<h3 id="方法区"><a href="#方法区" class="headerlink" title="方法区"></a>方法区</h3><ul>
<li><p>线程共享</p>
</li>
<li><p>用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。</p>
</li>
<li><p>虽然《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分，但是它却有一个别名叫作<strong>“非堆”（Non-Heap）</strong>，目的是<strong>与Java堆区分开来</strong>。</p>
</li>
<li><p>在JDK1.6及之前,使用<code>永久代</code>来实现方法区.</p>
<ul>
<li>-XX:MaxPermSize    设置永久代内存上限</li>
<li>-XX:PermSize    设置永久代内存</li>
</ul>
</li>
<li><p>JDK1.7把<code>字符串常量池</code>、<code>类的静态变量(class statics)</code>转移到了java heap,但是永久代还是存在,主要放一些类信息(<code>运算时常量池</code>)等.</p>
</li>
</ul>
<ul>
<li><p>JDK1.8彻底移除永久代,方法区采用本地内存中实现的元空间（Meta-space）来代替,将JDK1.7中永久代的信息移到了元空间,像<code>字符串常量池</code>和<code>静态变量</code>还是存在Java Heap中</p>
</li>
<li><p>如果方法区无法满足新的内存分配需求时，将抛出<strong>OutOfMemoryError异常</strong>。</p>
</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/jvm-javastack-EscapeAnalysis/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/jvm-javastack-EscapeAnalysis/" class="post-title-link" itemprop="url">JVM逃逸分析技术</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-05-26 16:02:00" itemprop="dateCreated datePublished" datetime="2020-05-26T16:02:00+00:00">2020-05-26</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>逃逸分析技术的日渐成熟,促使所有的Java对象实例不一定都在Java堆上分配内存</p>
<p>简单来讲就是，Java Hotspot 虚拟机可以分析<strong>新创建对象</strong>的使用范围，并决定是否在 Java 堆上分配内存的一项技术。</p>
<h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><ul>
<li>开启逃逸分析：-XX:+DoEscapeAnalysis</li>
<li>关闭逃逸分析：-XX:-DoEscapeAnalysis</li>
<li>显示分析结果：-XX:+PrintEscapeAnalysis</li>
<li>逃逸分析技术在 Java SE 6u23+ 开始支持,并默认设置为启用状态</li>
</ul>
<h2 id="逃逸程度"><a href="#逃逸程度" class="headerlink" title="逃逸程度"></a>逃逸程度</h2><p>逸分析的基本行为就是分析对象动态作用域,从<strong>不逃逸</strong>、<strong>方法逃逸</strong>到<strong>线程逃逸</strong>，称为对象<strong>由低到高的不同逃逸程度</strong>。</p>
<h3 id="方法逃逸"><a href="#方法逃逸" class="headerlink" title="方法逃逸"></a>方法逃逸</h3><p>当一个对象在<strong>方法中</strong>被定义后，它可能被<strong>外部方法</strong>所引用，例如作为调用参数传递到其他地方中，称为<strong>方法逃逸</strong>。</p>
 <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/*StringBuffer sb是一个方法内部变量，上述代码中直接将sb返回，这样这个StringBuffer有可能被其他方法所</span></span><br><span class="line"><span class="comment">*改变，这样它的作用域就不只是在方法内部，虽然它是一个局部变量，称其逃逸到了方法外部。甚至还有可能被外部线</span></span><br><span class="line"><span class="comment">*程访问到，譬如赋值给类变量或可以在其他线程中访问的实例变量，称为线程逃逸。</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> StringBuffer <span class="title">craeteStringBuffer</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">     StringBuffer sb = <span class="keyword">new</span> StringBuffer();</span><br><span class="line">     sb.append(s1);</span><br><span class="line">     sb.append(s2);</span><br><span class="line">     <span class="keyword">return</span> sb;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//上述代码如果想要StringBuffer sb不逃出方法，可以这样写：</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">createStringBuffer</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">     StringBuffer sb = <span class="keyword">new</span> StringBuffer();</span><br><span class="line">     sb.append(s1);</span><br><span class="line">     sb.append(s2);</span><br><span class="line">     <span class="keyword">return</span> sb.toString();</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<h3 id="线程逃逸"><a href="#线程逃逸" class="headerlink" title="线程逃逸"></a>线程逃逸</h3><ul>
<li>当一个对象在<strong>方法中</strong>被定义后，它可能被<strong>外部线程</strong>访问到，譬如赋值给可以在其他线程中访问的实例变量，这种称为<strong>线程逃逸</strong>。</li>
</ul>
<h2 id="逃逸分析优化"><a href="#逃逸分析优化" class="headerlink" title="逃逸分析优化"></a>逃逸分析优化</h2><p>如果能<strong>证明一个对象不会逃逸到方法或线程之外</strong>（换句话说是别的方法或线程无法通过任何途径访问到这个对象），或者<strong>逃逸程度比较低</strong>（只逃逸出方法而不会逃逸出线程），则可能为这个对象实例<strong>采取不同程度的优化</strong></p>
<h3 id="栈上分配（Stack-Allocations）"><a href="#栈上分配（Stack-Allocations）" class="headerlink" title="栈上分配（Stack Allocations）"></a>栈上分配（Stack Allocations）</h3><ul>
<li>如果确定一个对象<strong>不会逃逸出线程之外</strong>，那让这个对象在<strong>栈上分配内存</strong>将会是一个很不错的主意，对象所占用的内存空间就可以<strong>随栈帧出栈而销毁</strong>。</li>
<li>由于复杂度等原因，HotSpot中目前暂时还没有做这项优化，但一些其他的虚拟机（如Excelsior JET）使用了这项优化。</li>
<li>栈上分配可以支持方法逃逸，但不能支持线程逃逸。</li>
</ul>
<h3 id="标量替换（Scalar-Replacement）"><a href="#标量替换（Scalar-Replacement）" class="headerlink" title="标量替换（Scalar Replacement）"></a>标量替换（Scalar Replacement）</h3><ul>
<li>若一个数据已经无法再分解成更小的数据来表示了，Java虚拟机中的原始数据类型（int、long等数值类型及reference类型等）都不能再进一步分解了，那么这些数据就可以被称为<strong>标量</strong>。相对的，如果一个数据可以继续分解，那它就被称为<strong>聚合量（Aggregate）</strong>，Java中的对象就是典型的聚合量。</li>
<li>-XX:+EliminateAllocations    开启标量替换(jdk8默认开启)</li>
<li>-XX:+PrintEliminateAllocations    查看标量的替换情况</li>
<li>如果把一个Java对象拆散，根据程序访问的情况，将其用到的成员变量恢复为原始类型来访问，这个过程就称为<strong>标量替换</strong></li>
<li>假如逃逸分析能够证明一个对象<strong>不会被方法外部访问</strong>，并且这个对象可以被拆散，那么程序真正执行的时候将<strong>可能不去创建这个对象</strong>，而改为直接创建它的若干个被这个方法使用的<strong>成员变量</strong>来代替。</li>
<li>标量替换可以视作<strong>栈上分配的一种特例</strong>，实现更简单（不用考虑整个对象完整结构的分配），但对逃逸程度的要求更高，它<strong>不允许对象逃逸出方法范围内</strong>。</li>
</ul>
<h3 id="同步消除（Synchronization-Elimination）"><a href="#同步消除（Synchronization-Elimination）" class="headerlink" title="同步消除（Synchronization Elimination）"></a>同步消除（Synchronization Elimination）</h3><blockquote>
<p>也叫锁消除</p>
</blockquote>
<ul>
<li>+XX:+EliminateLocks    开启同步消除(jdk8默认开启)</li>
<li>线程同步本身是一个相对耗时的过程，如果逃逸分析能够确定一个变量<strong>不会逃逸出线程</strong>，无法被其他线程访问，那么这个变量的读写肯定就不会有竞争，对这个变量实施的<strong>同步措施</strong>也就可以<strong>安全地消除掉</strong>。</li>
<li>比如常用的线程安全类:<code>StringBuffer</code>,<code>HashTable</code>,<code>Vector</code>等.</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/archive/web-security/spring-security-oauth-server-demo/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/archive/web-security/spring-security-oauth-server-demo/" class="post-title-link" itemprop="url">基于SpringCloud搭建Spring-security-oauth认证服务器</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-05-19 20:25:06" itemprop="dateCreated datePublished" datetime="2020-05-19T20:25:06+00:00">2020-05-19</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/WebSecurity/" itemprop="url" rel="index"><span itemprop="name">WebSecurity</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="准备阶段"><a href="#准备阶段" class="headerlink" title="准备阶段"></a>准备阶段</h2><p>这里搭建一个用OAuth2.0密码模式认证的服务器，token存入redis，client存入Mysql；</p>
<p>所以事先要准备好：</p>
<ul>
<li>Redis</li>
<li>Mysql</li>
</ul>
<p>并且Mysql执行<a href="https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql" rel="noopener external nofollow noreferrer" target="_blank">Spring-security-oauth初始化Sql</a>这个SQL，初始化Spring-security-oauth所需要的表。然后执行</p>
<figure class="highlight sql"><table><tr><td class="code"><pre><span class="line"><span class="comment">-- 插入client_id和client_secret都为sunline的客户端</span></span><br><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> </span><br><span class="line">	oauth_client_details (client_id, client_secret, authorized_grant_types , autoapprove)</span><br><span class="line"><span class="keyword">values</span> </span><br><span class="line">	(<span class="string">"sunline"</span>,<span class="string">"	&#123;bcrypt&#125;$2a$10$G1CFd535SiyOtvi6ckbZWexQy.hW5x/I/fLBPiW/E4UmctCfKYbgG"</span>,<span class="string">"password"</span>,<span class="string">"true"</span>);</span><br></pre></td></tr></table></figure>

<blockquote>
<p>client_secret为<code>new BCryptPasswordEncoder().encode(&quot;sunline&quot;)</code>方法加密后，然后在加上<code>{bcrypt}</code></p>
</blockquote>
<h2 id="开始搭建"><a href="#开始搭建" class="headerlink" title="开始搭建"></a>开始搭建</h2><h3 id="导入pom依赖"><a href="#导入pom依赖" class="headerlink" title="导入pom依赖"></a>导入pom依赖</h3><figure class="highlight"><table><tr><td class="code"><pre><span class="line">&lt;!--security-oauth--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-cloud-starter-oauth2&lt;/artifactId&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br><span class="line">    </span><br><span class="line">&lt;!--redis--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-boot-starter-data-redis&lt;/artifactId&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br><span class="line">    </span><br><span class="line">&lt;!--mysql--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;mysql&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;8.0.17&lt;/version&gt;</span><br><span class="line">    &lt;scope&gt;compile&lt;/scope&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>

<h3 id="配置application-properties"><a href="#配置application-properties" class="headerlink" title="配置application.properties"></a>配置application.properties</h3><figure class="highlight properties"><table><tr><td class="code"><pre><span class="line"><span class="comment">#datasource</span></span><br><span class="line"><span class="meta">spring.datasource.url</span>=<span class="string">jdbc:mysql://localhost:3307/grey_code?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;serverTimezone=Asia/Shanghai</span></span><br><span class="line"><span class="meta">spring.datasource.username</span>=<span class="string">zmh</span></span><br><span class="line"><span class="meta">spring.datasource.password</span>=<span class="string">zmh</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#redis</span></span><br><span class="line"><span class="meta">spring.redis.host</span>=<span class="string">127.0.0.1</span></span><br><span class="line"><span class="meta">spring.redis.port</span>=<span class="string">6379</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">server.port</span>=<span class="string">9991</span></span><br><span class="line"><span class="meta">server.servlet.context-path</span>=<span class="string">/oauthServer</span></span><br></pre></td></tr></table></figure>

<h3 id="创建用户详情服务类"><a href="#创建用户详情服务类" class="headerlink" title="创建用户详情服务类"></a>创建用户详情服务类</h3><p><img src="http://cdn.mjava.top/blog/20200519194059.png" alt></p>
<h4 id="创建权限控制类"><a href="#创建权限控制类" class="headerlink" title="创建权限控制类"></a>创建权限控制类</h4><p><img src="http://cdn.mjava.top/blog/20200519194128.png" alt></p>
<h3 id="创建认证授权类"><a href="#创建认证授权类" class="headerlink" title="创建认证授权类"></a>创建认证授权类</h3><p><img src="http://cdn.mjava.top/blog/20200519194207.png" alt></p>
<h2 id="获取令牌"><a href="#获取令牌" class="headerlink" title="获取令牌"></a>获取令牌</h2><p>访问:<code>/oauth/token</code>就可以获取到令牌</p>
<p><img src="http://cdn.mjava.top/blog/20200519194446.png" alt></p>
<figure class="highlight json"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"accessToken"</span>: <span class="string">"e28f9a99-e60d-4693-b6c3-73e06a1d14f5ZMH10086"</span>,</span><br><span class="line">    <span class="attr">"expiration"</span>: <span class="string">"2020-05-19T21:11:39.883+0000"</span>,</span><br><span class="line">    <span class="attr">"scope"</span>: [</span><br><span class="line">        <span class="string">"all"</span></span><br><span class="line">    ],</span><br><span class="line">    <span class="attr">"tokenType"</span>: <span class="string">"bearer"</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="访问资源"><a href="#访问资源" class="headerlink" title="访问资源"></a>访问资源</h3><p>带上获取到的令牌</p>
<p><img src="http://cdn.mjava.top/blog/20200519194803.png" alt></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/page/6/">6</a><a class="extend next" rel="next" href="/page/3/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">灰灰</p>
  <div class="site-description" itemprop="description">浅水是喧哗的，深水是沉默的</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">59</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">16</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">56</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/greycode9" title="GitHub → https://github.com/greycode9" rel="noopener external nofollow noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:zhengminghui99@gmail.com" title="E-Mail → mailto:zhengminghui99@gmail.com" rel="noopener external nofollow noreferrer" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      Links
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://www.yuque.com/huihui-r7gwx" title="https://www.yuque.com/huihui-r7gwx" rel="noopener external nofollow noreferrer" target="_blank">语雀</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        
  <div class="beian"><a href="https://beian.miit.gov.cn" rel="noopener external nofollow noreferrer" target="_blank">赣ICP备17003482号 </a>
  </div>

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">灰灰</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io" class="theme-link" rel="noopener external nofollow noreferrer" target="_blank">Hexo</a> & <a href="https://muse.theme-next.org" class="theme-link" rel="noopener external nofollow noreferrer" target="_blank">NexT.Muse</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>
<script src="/js/utils.js"></script><script src="/js/motion.js"></script>
<script src="/js/schemes/muse.js"></script>
<script src="/js/next-boot.js"></script>



  




  <script src="/js/local-search.js"></script>












  

  
      

<script>
  if (typeof MathJax === 'undefined') {
    window.MathJax = {
      loader: {
          load: ['[tex]/mhchem'],
        source: {
          '[tex]/amsCd': '[tex]/amscd',
          '[tex]/AMScd': '[tex]/amscd'
        }
      },
      tex: {
        inlineMath: {'[+]': [['$', '$']]},
          packages: {'[+]': ['mhchem']},
        tags: 'ams'
      },
      options: {
        renderActions: {
          findScript: [10, doc => {
            document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
              const display = !!node.type.match(/; *mode=display/);
              const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
              const text = document.createTextNode('');
              node.parentNode.replaceChild(text, node);
              math.start = {node: text, delim: '', n: 0};
              math.end = {node: text, delim: '', n: 0};
              doc.math.push(math);
            });
          }, '', false],
          insertedScript: [200, () => {
            document.querySelectorAll('mjx-container').forEach(node => {
              let target = node.parentNode;
              if (target.nodeName.toLowerCase() === 'li') {
                target.parentNode.classList.add('has-jax');
              }
            });
          }, '', false]
        }
      }
    };
    (function () {
      var script = document.createElement('script');
      script.src = '//cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js';
      script.defer = true;
      document.head.appendChild(script);
    })();
  } else {
    MathJax.startup.document.state(0);
    MathJax.texReset();
    MathJax.typeset();
  }
</script><!-- hexo-inject:begin --><!-- hexo-inject:end -->

    

  

</body>
</html>
